package com.jerry.security.config;

import com.jerry.security.handler.MyAuthFailureHandler;
import com.jerry.security.handler.MyAuthSuccessHandler;
import com.jerry.security.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.social.security.SpringSocialConfigurer;

/**
 * // SpringBoot2.0 抛弃了原来的NoOpPasswordEncoder，要求用户保存的密码必须要使用加密算法后存储，
 * 在登录验证的时候Security会将获得的密码在进行编码后再和数据库中加密后的密码进行对比
 */
@Configuration
@EnableWebSecurity    //启动SpringSecurity过滤器链
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService myUserDetailsService;
    @Autowired
    private MyAuthFailureHandler myAuthFailureHandler;
    @Autowired
    private MyAuthSuccessHandler myAuthSuccessHandler;
    @Autowired
    private SpringSocialConfigurer springSocialConfigurer;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //该方法的作用就是代替xml中的<security:authentication-manager>配置
    //设置用户账号信息和权限
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 使用spring提供的加密方式对登录密码自动加密和自动验证。PasswordEncoder内部会调用encode方法进行加密，会调用matches方法进行密码验证
        // 注意：对同一个密码，每次加密出来的密码都不相同，可以有效防止密码破解。
        auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
    }

    //该方法的作用就是代替xml中的<security:http>配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/").permitAll()  //所有用户都可以访问根目录
            .antMatchers("/img/**").permitAll()  //所有用户都可以访问文件目录
            .antMatchers("/js/**").permitAll()  //所有用户都可以访问js文件
            .antMatchers("/customLogin").permitAll()  //所有用户都可以访问登录页面
            .anyRequest().fullyAuthenticated() //所有请求都需要认证才能访问
            .and()
            .logout().permitAll()  //所有用户都可以退出
            .and()
                .formLogin()
                .loginPage("/customLogin")
                .loginProcessingUrl("/authentication/formLogin")
                .successForwardUrl("/product/index")     //自定义表单登录
                .successHandler(myAuthSuccessHandler)
                .failureHandler(myAuthFailureHandler)   //成功和失败的handler
            .and()
            .csrf().disable()   //关闭Spring Security CSRF机制
            .apply(springSocialConfigurer);     //增加SpringSocial配置
    }


}
